// OPBFlash.v
// Copyright 2005, Pico Computing, Inc.
// This module manages the flash, and also the cpld since it shares most of the flash lines.

`include "PicoDefines.v"

module OPBFlash(
   FLASH_A_O, FLASH_A_I,
   FLASH_D,
   FLASH_OE,
   FLASH_WE,
   PEEKABOO, LOAD,
   OPB_Clk, OPB_Rst, OPB_ABus, OPB_BE, OPB_DBus,                  //OPB -> Slave Signals
   OPB_RNW, OPB_select, OPB_seqAddr,
   Sl_DBus, Sl_errAck, Sl_retry, Sl_toutSup, Sl_xferAck,          //Slave -> OPB Signals
   test_pins
);

parameter C_OPB_AWIDTH = 32;
parameter C_OPB_DWIDTH = 32;
parameter C_BASEADDR   = `OPB_KEYHOLE_BASEADDR;
parameter C_HIGHADDR   = `OPB_KEYHOLE_HIGHADDR;

output [25:0] FLASH_A_O;
input  [25:0] FLASH_A_I;
inout [15:0] FLASH_D;
output FLASH_OE;
output FLASH_WE;
output PEEKABOO;
output reg LOAD = 0;

input OPB_Clk;
input OPB_Rst;
input [C_OPB_AWIDTH-1:0] OPB_ABus;
input [(C_OPB_DWIDTH/8)-1:0] OPB_BE;
input [C_OPB_DWIDTH-1:0] OPB_DBus;
input OPB_RNW;
input OPB_select;
input OPB_seqAddr;
output [C_OPB_DWIDTH-1:0] Sl_DBus;
output Sl_errAck;
output Sl_retry;
output Sl_toutSup;
output Sl_xferAck;

output [127:0] test_pins;

reg [25:0] AddrLatch;

/* Trigger opb_en on CS and we/oe on RNW */
wire opb_en = OPB_select & (OPB_ABus >= C_BASEADDR && OPB_ABus <= C_HIGHADDR);
wire opb_we = opb_en & ~OPB_RNW;
wire opb_oe = opb_en & OPB_RNW;

/* Flash enables are active low */
assign FLASH_OE = ~opb_oe;
assign FLASH_WE = ~opb_we;
assign FLASH_A_O = LOAD ? AddrLatch[25:0] : OPB_ABus[26:1];

wire FLASH_D_T;
wire [15:0] FLASH_D_I, FLASH_D_O;

assign FLASH_D_T = opb_oe;
assign FLASH_D = ~FLASH_D_T ? FLASH_D_O : 16'hz;
assign FLASH_D_I = FLASH_D_T ? FLASH_D : 16'h0;

assign FLASH_D_O = OPB_DBus;
assign Sl_DBus = {FLASH_D_I, FLASH_D_I};

wire LoadReq = OPB_select & ~OPB_RNW & (OPB_ABus[31:0] == 32'h70000024);
always @(posedge OPB_Clk) begin
   if (LoadReq) begin
      AddrLatch[25:0] <= OPB_DBus[26:1];
      LOAD <= 1;
   end
end

/* Flash transactions will take up to 120ns to complete */
OPBWait #(.OPB_WAIT_CYCLES(12)) opb_wait(
   .opb_en(opb_en),
   .OPB_Clk(OPB_Clk),
   .OPB_Rst(OPB_Rst),
   .Sl_xferAck(Sl_xferAck)
);

assign Sl_errAck  = 1'b0;
assign Sl_retry   = 1'b0;
assign Sl_toutSup = 1'b0;

assign test_pins[127:0] = 128'h0;

/*
assign test_pins[31:0] = OPB_ABus[31:0];
assign test_pins[47:32] = OPB_DBus[15:0];
assign test_pins[63:48] = Sl_DBus[15:0];
assign test_pins[65:64] = OPB_BE[1:0];
assign test_pins[66] = OPB_select;
assign test_pins[67] = OPB_RNW;
assign test_pins[68] = OPB_Rst;
assign test_pins[69] = OPB_Clk;
assign test_pins[70] = Sl_xferAck;
assign test_pins[95:71] = FLASH_A_O;
assign test_pins[111:96] = FLASH_D;
assign test_pins[112] = FLASH_OE;
assign test_pins[113] = FLASH_WE;
assign test_pins[114] = 1'b1;
assign test_pins[115] = opb_en;
assign test_pins[116] = opb_we;
assign test_pins[117] = opb_oe;
assign test_pins[127:118] = 0;
*/

endmodule